package com.guosen.zebra.gateway.dao.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.guosen.App;
import com.guosen.zebra.core.common.ZebraConstants;
import com.guosen.zebra.core.grpc.anotation.ZebraConf;
import com.guosen.zebra.gateway.dao.RouteConfigDao;
import com.guosen.zebra.gateway.dto.ConfCenterRespDTO;
import com.guosen.zebra.gateway.dto.GatewayConf;
import com.guosen.zebra.gateway.route.model.RouteConfig;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Component
public class RouteConfigDaoImpl implements RouteConfigDao {

    private static final Logger LOGGER = LoggerFactory.getLogger(RouteConfigDaoImpl.class);

    private static final OkHttpClient HTTP_CLIENT = new OkHttpClient();

    private static final ZebraConf ZEBRA_CONF = App.class.getAnnotation(ZebraConf.class);

    @Override
    public List<RouteConfig> getConfigs() {
        JSONArray gatewayConfigJSONArray = doHttpConfigGet();
        if (gatewayConfigJSONArray == null) {
            return Collections.emptyList();
        }

        List<GatewayConf> gatewayConfigs = gatewayConfigJSONArray.toJavaList(GatewayConf.class);
        if (CollectionUtils.isEmpty(gatewayConfigs)) {
            return Collections.emptyList();
        }

        return toRouteConfig(gatewayConfigs);
    }

    private JSONArray doHttpConfigGet() {
        JSONArray httpConfigObj = null;
        Request request = new Request.Builder().url(ZEBRA_CONF.confaddr() + "/zebra-conf/getGatewayConf").build();
        try (Response response = HTTP_CLIENT.newCall(request).execute()){
            ResponseBody responseBody = response.body();
            if (responseBody == null) {
                return null;
            }

            String responseBodyStr = responseBody.string();
            ConfCenterRespDTO confCenterRespDTO = JSONObject.parseObject(responseBodyStr, ConfCenterRespDTO.class);
            if (confCenterRespDTO.getCode() == ZebraConstants.SUCCESS) {
                httpConfigObj = (JSONArray) confCenterRespDTO.getData();
            }
            else {
                LOGGER.error("Failed to query route config, error message {}", confCenterRespDTO.getMsg());
            }
        } catch (IOException e) {
            LOGGER.error("Failed to query route config.", e);
        }

        return httpConfigObj;
    }

    private List<RouteConfig> toRouteConfig(List<GatewayConf> gatewayConfigs) {
        List<RouteConfig> routeConfigs = new ArrayList<>(gatewayConfigs.size());

        for (GatewayConf gatewayConf : gatewayConfigs) {
            RouteConfig routeConfig = new RouteConfig();
            routeConfig.setServiceName(gatewayConf.getService());
            routeConfig.setVersion(gatewayConf.getVersion());
            routeConfig.setUrlPrefix(gatewayConf.getPath());
            routeConfig.setGroup(gatewayConf.getGroup());
            routeConfig.setMethodMappings(gatewayConf.getText());

            routeConfigs.add(routeConfig);
        }

        return routeConfigs;
    }
}
